home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / jcool01.zip / BIT_SET.C < prev    next >
C/C++ Source or Header  |  1992-08-20  |  29KB  |  848 lines

  1. //
  2. // Copyright (C) 1991 Texas Instruments Incorporated.
  3. //
  4. // Permission is granted to any individual or institution to use, copy, modify,
  5. // and distribute this software, provided that this complete copyright and
  6. // permission notice is maintained, intact, in all copies and supporting
  7. // documentation.
  8. //
  9. // Texas Instruments Incorporated provides this software "as is" without
  10. // express or implied warranty.
  11. //
  12. //
  13. // Created: MBN 06/13/89 -- Initial implementation
  14. // Updated: MBN 09/31/89 -- Added conditional exception handling
  15. // Updated: MBN 10/07/89 -- Changed operator[-~^&|] to allocate on stack
  16. //                          Bit_Set::find(int) returns state of indicated bit
  17. // Updated: MBN 10/12/89 -- Changed "current_position" to "curpos" and added
  18. //                          the current_position() method for Iterator<Type>
  19. // Updated: MBN 10/13/89 -- Changed from bit field to preprocessor bit macros
  20. // Updated: LGO 11/09/89 -- Major changes to every method
  21. // Updated: MBN 01/10/90 -- Fixed size-check bug in operator=
  22. // Updated: MJF 03/12/90 -- Added group names to RAISE
  23. // Updated: DLS 03/26/91 -- New lite version
  24. // Updated: VDN 05/01/92 -- Copying by bytes only, to avoid out of bounds.
  25. // Updated: JAM 08/12/92 -- removed DOS specifics, stdized #includes
  26. // Updated: JAM 08/19/92 -- added static data def
  27. //
  28. // This file contains member and  friend function implementation  code for  the
  29. // Bit Set class defined in the  Bit_Set.h header file.  Where  appropriate and
  30. // possible,  interfaces to, and  us  of, existing system   functions  has been
  31. // incorporated.  An overview of the structure of the CoolBit_Set class, along with
  32. // a synopsis of each member and friend function, can be found in the Bit_Set.h
  33. // header file.
  34. //
  35.  
  36. #ifndef BIT_SET_H                // If no class definition
  37. #include <cool/Bit_Set.h>            // Include class specification
  38. #endif
  39.  
  40. #include <string.h>                // For strcpy
  41. #include <stdlib.h>                // For exit()
  42.  
  43. #define BS_MAKE_POSITION(byte, offset) ((byte << 3) | offset)
  44. #define BS_BYTE_COUNT(n) ((int) (n + 7) >> 3)    // Byte count from bit count
  45.  
  46. extern int bit_pos[];                // Lowest/highest bit set masks
  47. extern int bits_set[];                // Number of bits set in mask
  48. extern int powers_of_2_minus_1[];        // Number of contiguous bits
  49.  
  50.  
  51. // alloc_size_s -- Allocation size for growth
  52. int CoolBit_Set::alloc_size_s = BIT_SET_BLK_SZ;        // Set memory block size
  53.  
  54.  
  55. // CoolBit_Set -- Simple constructor that takes no arguments and allocates no
  56. //            storage
  57. // Input:     None
  58. // Output:    None
  59.  
  60. CoolBit_Set::CoolBit_Set () {
  61.   this->data = NULL;                // Zero initial memory
  62.   this->size = 0;                // Save number of bytes
  63.   this->number_elements = 0;            // Save number of elements
  64.   this->curpos = INVALID;            // Reset current position
  65.   this->growth_ratio = 0.0;            // Initialize growth ratio
  66. }
  67.  
  68.  
  69. // CoolBit_Set -- Constructor that takes an integer argument specifying an initial
  70. //            number of elements for which storage must be allocated
  71. // Input:     Initial number of elements
  72. // Output:    None
  73.  
  74. CoolBit_Set::CoolBit_Set (int n) {
  75.   int nbyte = BS_BYTE_COUNT(n);
  76.   this->data = new unsigned char[nbyte];    // Allocate storage
  77.   for (int i = 0; i < nbyte; i++) data[i] = 0;    // Initialize bits to zero
  78.   this->size = nbyte;                // Save number of bytes
  79.   this->number_elements = 0;            // Save number of elements
  80.   this->curpos = INVALID;            // Reset current position
  81.   this->growth_ratio = 0.0;            // Initialize growth ratio
  82. }
  83.  
  84.  
  85. // CoolBit_Set -- Constructor that takes a reference to another CoolBit_Set object and
  86. //            duplicates its size and value
  87. // Input:     Reference to Bit_Set object
  88. // Output:    None
  89.  
  90. CoolBit_Set::CoolBit_Set (const CoolBit_Set& b) {
  91.   this->data = new unsigned char[b.size];      // Allocate storage
  92.   for (int i = 0; i < b.size; i++)          // For each byte in vector
  93.     this->data[i] = b.data[i];              // Copy value
  94.   this->size = b.size;                  // Maintain number of bytes
  95.   this->number_elements = b.number_elements;      // Save number of elements
  96.   this->curpos = INVALID;              // Reset current position
  97.   this->growth_ratio = 0.0;              // Initialize growth ratio
  98. }
  99.  
  100.  
  101. // ~CoolBit_Set -- Destructor for CoolBit_Set objects
  102. // Input:      None
  103. // Output:     None
  104.  
  105. CoolBit_Set::~CoolBit_Set () {
  106.   delete [] this->data;                // Free up memory allocated
  107. }
  108.  
  109. // MACRO generate_next(operation=, excess_a=0, excess_b=0) {
  110. //   int index, offset;
  111. //   long pos = this->curpos;
  112. //   if (pos == INVALID) {            // If invalid current position
  113. //     index = 0;                // Start at first byte
  114. //     offset = -1;                // Start at zero'th bit
  115. //   } else {
  116. //     index = BS_BYTE_NUMBER(pos);        // Get current byte index
  117. //     offset = BS_BYTE_OFFSET(pos);        // Get current bit offset
  118. //   }
  119. // 
  120. // #if excess_a || excess_b  
  121. //   int end = min(this->number_elements, b.number_elements);
  122. // #else
  123. //   int end = this->number_elements;
  124. // #endif
  125. //   register int value = (~powers_of_2_minus_1[offset+1]);
  126. //   while(index < end) {
  127. //     value &= this->data[index] operation;
  128. //     if (value != 0) goto found;
  129. //     value = -1;
  130. //     index++;
  131. //   }
  132. // #if excess_a || excess_b  
  133. //   if (index < (end = this->number_elements)) {
  134. // #if excess_a
  135. //     while(index < end) {
  136. //       value &= this->data[index];
  137. //       if (value != 0) goto found;
  138. //       value = -1;
  139. //       index++;
  140. //     }
  141. // #endif
  142. //   } else {
  143. // #if excess_b
  144. //     end = b.number_elements;
  145. //     while(index < end) {
  146. //       value &= b.data[index];
  147. //       if (value != 0) goto found;
  148. //       value = -1;
  149. //       index++;
  150. //     }
  151. // #endif
  152. //   }
  153. // #endif
  154. //   this->curpos = INVALID;            // Invalidate current position
  155. //   return FALSE;                // Return failure
  156. //  found:
  157. //   this->curpos = BS_MAKE_POSITION(index, bit_pos[value]); 
  158. //   return TRUE;                // Indicate success
  159. // }
  160.  
  161.  
  162. // next -- Increment the current position index
  163. // Input:  None
  164. // Output: Boolean TRUE/FALSE
  165.  
  166. Boolean CoolBit_Set::next () {
  167.   //generate_next()                             // take out this macro expansion
  168.   
  169.   int index, offset;
  170.   long pos = this->curpos;
  171.   if (pos == (-1)) {
  172.     index = 0;
  173.     offset = -1;
  174.   } else {
  175.     index = ((int) (pos >> 3));
  176.     offset = ((int) (pos & 0x07));
  177.   }
  178.   int end = this->number_elements;
  179.   register int value = (~powers_of_2_minus_1[offset+1]);
  180.   while(index < end) {
  181.     value &= this->data[index] ;
  182.     if (value != 0) goto found;
  183.     value = -1;
  184.     index++;
  185.   }
  186.   this->curpos = (-1);
  187.   return (0);
  188.  found:
  189.   this->curpos = ((index << 3) | bit_pos[value]);
  190.   return (1);
  191. }
  192.  
  193.  
  194. // next_intersection -- Position at the zero-relative integer of the next bit
  195. //                      in the intersection of two bit sets.
  196. // Input:               Reference to Bit Set object
  197. // Output:              TRUE/FALSE, current position updated
  198.  
  199. Boolean CoolBit_Set::next_intersection (const CoolBit_Set& b) {
  200.   if (this->number_elements > b.number_elements)
  201.     this->number_elements = b.number_elements;
  202.   //generate_next(&b.data[index],0,0)               // take out macro expansion
  203.   
  204.   int index, offset;
  205.   long pos = this->curpos;
  206.   if (pos == (-1)) {
  207.     index = 0;
  208.     offset = -1;
  209.   } else {
  210.     index = ((int) (pos >> 3));
  211.     offset = ((int) (pos & 0x07));
  212.   }
  213.   int end = this->number_elements;
  214.   register int value = (~powers_of_2_minus_1[offset+1]);
  215.   while(index < end) {
  216.     value &= this->data[index] &b.data[index];
  217.     if (value != 0) goto found;
  218.     value = -1;
  219.     index++;
  220.   }
  221.   this->curpos = (-1);
  222.   return (0);
  223.  found:
  224.   this->curpos = ((index << 3) | bit_pos[value]);
  225.   return (1);
  226. }
  227.  
  228.  
  229. // next_union -- Position at the zero-relative integer of the next bit in 
  230. //               the union of two bit sets.
  231. // Input:        Reference to Bit Set object
  232. // Output:       TRUE/FALSE, current position updated
  233.  
  234. Boolean CoolBit_Set::next_union (const CoolBit_Set& b) {
  235.   //generate_next(|b.data[index],1,1)         // take out macro expansion
  236.   
  237.   int index, offset;
  238.   long pos = this->curpos;
  239.   if (pos == (-1)) {
  240.     index = 0;
  241.     offset = -1;
  242.   } else {
  243.     index = ((int) (pos >> 3));
  244.     offset = ((int) (pos & 0x07));
  245.   }
  246.   int end = min(this->number_elements, b.number_elements);
  247.   register int value = (~powers_of_2_minus_1[offset+1]);
  248.   while(index < end) {
  249.     value &= this->data[index] |b.data[index];
  250.     if (value != 0) goto found;
  251.     value = -1;
  252.     index++;
  253.   }
  254.   if (index < (end = this->number_elements)) {
  255.     while(index < end) {
  256.       value &= this->data[index];
  257.       if (value != 0) goto found;
  258.       value = -1;
  259.       index++;
  260.     }
  261.   } else {
  262.     end = b.number_elements;
  263.     while(index < end) {
  264.       value &= b.data[index];
  265.       if (value != 0) goto found;
  266.       value = -1;
  267.       index++;
  268.     }
  269.   }
  270.   this->curpos = (-1);
  271.   return (0);
  272.  found:
  273.   this->curpos = ((index << 3) | bit_pos[value]);
  274.   return (1);
  275. }
  276.  
  277. // next_difference -- Position at the zero-relative integer of the next bit in 
  278. //                    the difference of two bit sets. That is all elements in
  279. //                    "this" that are not in "b"
  280. // Input:             Reference to Bit Set object
  281. // Output:            TRUE/FALSE, current position updated
  282.  
  283. Boolean CoolBit_Set::next_difference (const CoolBit_Set& b) {
  284.   //generate_next(&~b.data[index],1,0)      // take out macro expansion
  285.   
  286.   int index, offset;
  287.   long pos = this->curpos;
  288.   if (pos == (-1)) {
  289.     index = 0;
  290.     offset = -1;
  291.   } else {
  292.     index = ((int) (pos >> 3));
  293.     offset = ((int) (pos & 0x07));
  294.   }
  295.   int end = min(this->number_elements, b.number_elements);
  296.   register int value = (~powers_of_2_minus_1[offset+1]);
  297.   while(index < end) {
  298.     value &= this->data[index] &~b.data[index];
  299.     if (value != 0) goto found;
  300.     value = -1;
  301.     index++;
  302.   }
  303.   if (index < (end = this->number_elements)) {
  304.     while(index < end) {
  305.       value &= this->data[index];
  306.       if (value != 0) goto found;
  307.       value = -1;
  308.       index++;
  309.     }
  310.   } else {
  311.   }
  312.   this->curpos = (-1);
  313.   return (0);
  314.  found:
  315.   this->curpos = ((index << 3) | bit_pos[value]);
  316.   return (1);
  317. }
  318.  
  319. // next_xor -- Position at the zero-relative integer of the next bit in 
  320. //             the XOR of two bit sets.
  321. // Input:      Reference to Bit Set object
  322. // Output:     TRUE/FALSE, current position updated
  323.  
  324. Boolean CoolBit_Set::next_xor (const CoolBit_Set& b) {
  325.   //generate_next(^b.data[index];,1,1)     // take out macro expansion
  326.   
  327.   int index, offset;
  328.   long pos = this->curpos;
  329.   if (pos == (-1)) {
  330.     index = 0;
  331.     offset = -1;
  332.   } else {
  333.     index = ((int) (pos >> 3));
  334.     offset = ((int) (pos & 0x07));
  335.   }
  336.   int end = min(this->number_elements, b.number_elements);
  337.   register int value = (~powers_of_2_minus_1[offset+1]);
  338.   while(index < end) {
  339.     value &= this->data[index] ^b.data[index];;
  340.     if (value != 0) goto found;
  341.     value = -1;
  342.     index++;
  343.   }
  344.   if (index < (end = this->number_elements)) {
  345.     while(index < end) {
  346.       value &= this->data[index];
  347.       if (value != 0) goto found;
  348.       value = -1;
  349.       index++;
  350.     }
  351.   } else {
  352.     end = b.number_elements;
  353.     while(index < end) {
  354.       value &= b.data[index];
  355.       if (value != 0) goto found;
  356.       value = -1;
  357.       index++;
  358.     }
  359.   }
  360.   this->curpos = (-1);
  361.   return (0);
  362.  found:
  363.   this->curpos = ((index << 3) | bit_pos[value]);
  364.   return (1);
  365. }
  366.  
  367.  
  368. // prev -- Decrement the current position index
  369. // Input:  None
  370. // Output: Boolean TRUE/FALSE
  371.  
  372. Boolean CoolBit_Set::prev () {
  373.   int index, value, offset;
  374.   long pos = this->curpos;
  375.   if (pos == INVALID) {                // If invalid current position
  376.     index = this->number_elements;        // Start at last byte
  377.     offset = BS_BITSPERBYTE;            // Start at last bit bit
  378.   } else {
  379.     index = BS_BYTE_NUMBER(pos);        // Get current byte index
  380.     offset = BS_BYTE_OFFSET(pos);        // Get current bit offset
  381.   }
  382.   value = (this->data[index] & 
  383.        (~powers_of_2_minus_1[offset-1]));    //Reset low bits
  384.   while (value == 0) {                // If no more bits set
  385.     if (index <0){                // If we are at start of vector
  386.       this->curpos = INVALID;            // Invalidate current position
  387.       return FALSE;                // Return failure
  388.     }
  389.     value = this->data[--index];        // Else get next byte value
  390.   }
  391.     this->curpos = BS_MAKE_POSITION(index,bit_pos[value]);
  392.   return TRUE;                    // Indicate success
  393. }
  394.  
  395.  
  396. // find -- Set the current position to the nth bit
  397. // Input:  Bit position desired (really, it's an integer value)
  398. // Output: TRUE/FALSE
  399.  
  400. Boolean CoolBit_Set::find (int n) {
  401. #if ERROR_CHECKING
  402.   if (BS_BYTE_NUMBER(n) >= this->size) {    // If outside allocated range
  403.     this->find_error (n);            // Raise exception
  404.     this->curpos = INVALID;            // Invalidate current position
  405.     return FALSE;                // Return failure
  406.   }
  407. #endif
  408.     this->curpos = n;
  409.   return(((this->data[BS_BYTE_NUMBER(n)]) >> BS_BYTE_OFFSET(n)) & 0x01);
  410. }
  411.  
  412.  
  413. // put -- Put an element to the set
  414. // Input: Bit position desired (really, it's an integer value)
  415. // Output: TRUE/FALSE
  416.  
  417. Boolean CoolBit_Set::put (int n) {
  418.   int nbytes = BS_BYTE_COUNT(n+1);        // Calculate byte index
  419.   if (nbytes >= this->number_elements) {    // If bigger than largest
  420.     if (nbytes >= this->size)            // If outside allocated range
  421.       this->grow (n);                // Grow the bit vector
  422.     this->number_elements = nbytes;
  423.   }
  424.   this->data[BS_BYTE_NUMBER(n)] |= (1 << BS_BYTE_OFFSET(n)); // Set proper bit
  425.   this->curpos = n;
  426.   return TRUE;                    // Return success
  427. }
  428.  
  429.  
  430. // put -- Put a range of elements to the set
  431. // Input: Start, end bit positions (really, they're just integer values)
  432. // Output: TRUE/FALSE
  433.  
  434. Boolean CoolBit_Set::put (int start, int end) {
  435.   if (start > end) {                // If start is passed the end!
  436. #if ERROR_CHECKING
  437.     this->put_error (start,end);        // Raise exception
  438. #endif
  439.     this->curpos = INVALID;            // Invalidate current position
  440.     return FALSE;                // Return failure
  441.   }
  442.   int last = BS_BYTE_COUNT(end);
  443.   if (last >= this->number_elements) {
  444.     if (last >= this->size)
  445.       this->grow (end);                // Grow the bit vector
  446.     this->number_elements = last;
  447.   }
  448.   // This could be made MUCH faster by banging a byte at a time
  449.   for (int i = start; i <= end; i++) // For each element in range
  450.     this->data[BS_BYTE_NUMBER(i)] |= (1 << (BS_BYTE_OFFSET(i))); // Set bit
  451.   this->curpos = start;
  452.   return TRUE;                    // Return success
  453. }
  454.  
  455.  
  456. // remove -- Remove element from set at current position
  457. // Input:    None
  458. // Output:   TRUE/FALSE
  459.  
  460. Boolean CoolBit_Set::remove () {
  461. #if ERROR_CHECKING
  462.   if (this->curpos == INVALID) {        // If current position INVALID
  463.     this->remove_error ();            // Raise exception
  464.     return FALSE;                // Return failure
  465.   }
  466. #endif
  467.   int mask = ~(1 << BS_BYTE_OFFSET(this->curpos)); // Make bit mask
  468.   this->data[BS_BYTE_NUMBER(this->curpos)] &= mask; // Turn off bit
  469.   return TRUE;
  470. }
  471.  
  472.  
  473. // remove -- Remove the specified element from the set
  474. // Input:    Element to be removed (really just an integer value)
  475. // Output:   TRUE/FALSE
  476.  
  477. Boolean CoolBit_Set::remove (int n) {
  478.   if (BS_BYTE_NUMBER(n) >= this->number_elements) // If out of range
  479.     return FALSE;                  // Return failure
  480.   int mask = ~(1 << BS_BYTE_OFFSET(n));          // Make bit mask
  481.   this->data[BS_BYTE_NUMBER(n)] &= mask;      // Turn off bit
  482.   this->curpos = n;
  483.   return TRUE;                    // Return success
  484. }
  485.  
  486.  
  487. // remove -- Remove range of elements from the set
  488. // Input:    Start, end bit positions (really, they're just integer values)
  489. // Output:   TRUE/FALSE
  490.  
  491. Boolean CoolBit_Set::remove (int start, int end) {
  492. #if ERROR_CHECKING
  493.   if (start > end) {
  494.     this->rem_start_end_error (start,end);    // Raise exception
  495.     this->curpos = INVALID;            // Invalidate current pos
  496.     return FALSE;                // Return failure
  497.   }
  498. #endif
  499.     if (BS_BYTE_NUMBER(start) >= this->number_elements) {
  500.     this->curpos = INVALID;            // Invalidate current pos
  501.     return FALSE;                // Return failure
  502.   }
  503.   if (BS_BYTE_NUMBER(end) >= this->number_elements)
  504.     end = this->number_elements * BS_BITSPERBYTE;
  505.   for (int i = start; i <= end; i++)         // For each element in range
  506.     this->data[BS_BYTE_NUMBER(i)] &= ~(1 << (BS_BYTE_OFFSET(i))); // Reset bit
  507.   this->curpos = start;
  508.   return TRUE;                    // Return success
  509. }
  510.  
  511.  
  512. // search -- Determine if one Bit Set is a subset of another
  513. // Input:    Reference to a Bit Set object
  514. // Output:   TRUE/FALSE
  515.  
  516. Boolean CoolBit_Set::search (const CoolBit_Set& b) const {
  517.   int len = min(this->number_elements, b.number_elements);
  518.   for (int i = 0; i < len; i++)            // For each byte in set
  519.     if ((this->data[i] & b.data[i]) != b.data[i]) // If not as first set
  520.       return FALSE;                  // Then not a subset
  521.   if (i < b.number_elements)              // If more elements in 2nd
  522.     for (; i < b.number_elements; i++)          // Its still subset if all
  523.       if (b.data[i] != 0)              // other elemenst are 0
  524.     return FALSE;                  // Nope! Return failure
  525.   return TRUE;                      // Subset; return success
  526. }
  527.  
  528.  
  529. // operator- -- Overload unary minus operator to return elements not in set
  530. // Input:       None
  531. // Output:      Bit Set object containing complement of this set
  532.  
  533. CoolBit_SetE CoolBit_Set::operator- () {
  534.   CoolBit_Set temp (this->number_elements * BS_BITSPERBYTE);    // New bit set
  535.   for (int i = 0; i < this->number_elements; i++) // For each byte in vector
  536.     temp.data[i] = ~(this->data[i]);        // Copy complement of set
  537.   temp.curpos = INVALID;            // Reset current position
  538.   temp.number_elements = this->number_elements; // Update number of elements
  539.   CoolBit_SetE& result = (CoolBit_SetE&) temp;    // same physical object
  540.   return result;                // shallow swap on return
  541. }
  542.  
  543.  
  544. // MACRO generate_set_operator(a, b, op, excess=0) {
  545. //   int a_size = BS_WORD_COUNT(a->number_elements);
  546. //   int b_size = BS_WORD_COUNT(b.number_elements);
  547. //   unsigned int* a_data = (unsigned int*) a->data;
  548. //   unsigned int* b_data = (unsigned int*) b.data;
  549. //   int min_size = min(a_size, b_size);
  550. //   for (int i = 0; i < min_size; i++)
  551. //     a_data[i] = a_data[i] op b_data[i];        // 
  552. //   for (; i < b_size; i++)
  553. //     a_data[i] = excess;                // operate on excess b's
  554. // }
  555.  
  556.  
  557. #define generate_set_operator(a, b, op, excess)                          \
  558.   int a_size = a->number_elements;                                \
  559.   int b_size = b.number_elements;                                 \
  560.   unsigned char* a_data = a->data;                            \
  561.   unsigned char* b_data = b.data;                             \
  562.   int min_size = min(a_size, b_size);                         \
  563.   for (int i = 0; i < min_size; i++)                          \
  564.      a_data[i] = a_data[i] op b_data[i];    /*operate on common sets*/    \
  565.   for (; i < b_size; i++)                                       \
  566.      a_data[i] = excess;            /*operate on excess b's*/
  567.  
  568.  
  569. // operator|= -- Determine the union of two sets, that is all elements in each
  570. //               set and destructively modify the first set with the result
  571. // Input:        Reference to a bit set
  572. // Output:       Updated Bit Set object containing union of two sets
  573.  
  574. CoolBit_Set& CoolBit_Set::operator|= (const CoolBit_Set& b) {
  575.   if (b.number_elements > this->size)
  576.     this->grow(b.number_elements * BS_BITSPERBYTE);
  577.   generate_set_operator(this, b, |, b_data[i]); // Calculate the union
  578.   if (this->number_elements < b.number_elements)
  579.     this->number_elements = b.number_elements;
  580.   this->curpos = INVALID;            // Invalidate current position
  581.   return *this;                    // Return refenerce
  582. }
  583.  
  584.  
  585. // operator-= -- Determine the difference of two sets, that is all elements in
  586. //               the first set that are not in the second and destructively
  587. //               modify the first with the result
  588. // Input:        Reference to bit set
  589. // Output:       Updated Bit Set object containing union of two sets
  590.  
  591. CoolBit_Set& CoolBit_Set::operator-= (const CoolBit_Set& b) {
  592.   generate_set_operator(this, b, &~, 0);    // Calculate the difference
  593.   this->curpos = INVALID;            // Invalid current position
  594.   return *this;                    // Return refenerce
  595. }
  596.  
  597.  
  598. // operator^= -- Determine the exclusive-OR of two sets, that is all elements
  599. //               in the first set that are not in the second and all elements
  600. //               in the second set that are not in the first and destructively 
  601. //               modify the first with the result
  602. // Input:        Reference to bit set
  603. // Output:       Updated Bit Set object containing XOR of two sets
  604.  
  605. CoolBit_Set& CoolBit_Set::operator^= (const CoolBit_Set& b) {
  606.   if (b.number_elements > this->size)
  607.     this->grow(b.number_elements * BS_BITSPERBYTE);
  608.   generate_set_operator(this, b, ^, b_data[i]); // Calculate the exclusive-OR
  609.   if (this->number_elements < b.number_elements)
  610.     this->number_elements = b.number_elements;
  611.   this->curpos = INVALID;            // Invalidate current position
  612.   return *this;                    // Return refenerce
  613. }
  614.  
  615.  
  616. // operator&= -- Determine the intersection of two sets, that is all elements 
  617. //               that are in both sets and destructively modify the first with
  618. //               the result
  619. // Input:        Reference to Bit Set object
  620. // Output:       Updated Bit Set object containing intersection of two sets
  621.  
  622. CoolBit_Set& CoolBit_Set::operator&= (const CoolBit_Set& b) {
  623.   generate_set_operator(this, b, &, 0);        // Calculate the exclusive-OR
  624.   if (this->number_elements > b.number_elements) {
  625.     this->number_elements = b.number_elements;    // shorten ourself
  626.     for (; i < a_size; i++) a_data[i] = 0;    // and Zap excess bits
  627.   }
  628.   this->curpos = INVALID;            // Invalid current position
  629.   return *this;                    // Return refenerce
  630. }
  631.  
  632.  
  633. // clear -- Remove all elements from the set
  634. // Input:   None
  635. // Output:  None
  636.  
  637. void CoolBit_Set::clear () {
  638.   for (int i = 0; i < this->number_elements; i++) 
  639.     this->data[i] = 0;                // Initialize bits to zero
  640.   this->curpos = INVALID;            // Invalidate current position
  641. }
  642.  
  643.  
  644. // grow -- resize the bit set (private method)
  645. // Input:    Minimum size requirement
  646. // Output:   none
  647.  
  648. void CoolBit_Set::grow (int min_size) {
  649.   if (this->growth_ratio != 0.0 &&
  650.       (this->size * (1.0+growth_ratio)) >= min_size)
  651.     min_size = (int)(this->size * (1.0 + growth_ratio)); // New size
  652.   else
  653.     min_size += alloc_size_s;            // Update vector size
  654.   resize(min_size);
  655. }
  656.  
  657.  
  658. // resize -- Resize the bit set for at least some specified number of elements
  659. // Input:    Minimum size requirement
  660. // Output:   TRUE/FALSE
  661.  
  662. void CoolBit_Set::resize (int n) {
  663.   int nbytes = BS_BYTE_COUNT(n);
  664.   unsigned char* temp = new unsigned char[nbytes]; // Allocate storage
  665.   for (int i = 0; i < this->number_elements; i++) 
  666.     temp[i] = this->data[i];            // copy old data
  667.   for (; i < nbytes; i++)
  668.     temp[i] = 0;                // clear new data
  669.   delete [] this->data;                // Free old storage
  670.   this->data = temp;                // Point to new storage
  671.   this->size = nbytes;                // Save number of bytes
  672.   this->curpos = INVALID;            // Reset current position
  673. }
  674.  
  675.  
  676. // operator= -- Overload the assignment operator for Bit Set objects
  677. // Input:       Reference to Bit Set object
  678. // Output:      Reference to Bit Set object
  679.  
  680. CoolBit_Set& CoolBit_Set::operator= (const CoolBit_Set& b) {
  681.   if (this != &b) {
  682.     int len = b.size;                // Get size of object to copy
  683.     if (this->size < len) {            // If not enough storage
  684.       delete [] this->data;            // Deallocate old storage
  685.       this->data = new unsigned char[len];    // Allocate same size storage
  686.       this->size = len;                // Maintain number of bytes
  687.     }
  688.     for (int i = 0; i < len; i++)
  689.       this->data[i] = b.data[i];        // copy all bytes
  690.     this->number_elements = b.number_elements;
  691.     this->curpos = INVALID;            // Reset current position
  692.   }
  693.   return *this;                    // Return reference to object
  694. }
  695.  
  696.  
  697. // operator<< -- Overload the output operator for Bit Set objects
  698. // Input:        Reference to stream, reference to Bit Set object
  699. // Output:       Reference to stream
  700.  
  701. ostream& operator<< (ostream& os, const CoolBit_Set& b) {
  702.   static char ascii_rep[10];            // Static storage for 0's/1's
  703.   os << "[ ";                    // Output start of set bracket
  704.   for (int i = 0; i < b.number_elements; i++) {    // For each byte in the set
  705.     strcpy (ascii_rep, "00000000 ");        // Assume majority of zeros
  706.     for (int j = 7; j >= 0; j--)
  707.       if (b.data[i] & (1 << j))
  708.     ascii_rep[j] = '1';            // Copy "1" character to string
  709.     os << ascii_rep;                // Output 0's and 1's for byte
  710.   }
  711.   os << "]\n";                    // Output terminating bracket
  712.   return os;                    // Return reference to stream
  713. }
  714.  
  715.  
  716. // operator== -- Overload the equality operator for Bit Set objects
  717. // Input:        Reference to Bit Set object
  718. // Output:       TRUE/FALSE
  719.  
  720. Boolean operator== (const CoolBit_Set& b1, const CoolBit_Set& b2) {
  721.   int len = min(b1.number_elements, b2.number_elements); // common length
  722.   for (int i = 0; i < len; i++)                   
  723.     if (b1.data[i] != b2.data[i])          // Check for different bits
  724.       return FALSE;                  // in common section
  725.   for (i = len; i < b1.number_elements; i++)      // Check for nonzero bits in
  726.     if (b1.data[i])                  // extra section of this
  727.       return FALSE;                  
  728.   for (i = len; i < b2.number_elements; i++)      // Check for nonzero bits in
  729.     if (b2.data[i])                  // extra section of b
  730.       return FALSE;                  
  731.   return TRUE;                      // Return success indication
  732. }
  733.  
  734.  
  735. // length -- Return number of elements in Set
  736. // Input:    None
  737. // Output:   Integer representing number of bits set 
  738.  
  739. int CoolBit_Set::length () const {
  740.   int count = 0;                // Temporary to hold count
  741.   int len = this->number_elements;
  742.   for (int i = 0; i < len; i++)            // For each byte in the vector
  743.     count += bits_set[this->data[i]];        // Add to count number bits set
  744.   return count;                    // Return element count 
  745. }
  746.  
  747.  
  748. // value_error -- Raise exception for CoolBit_Set::value() method
  749. // Input:         None
  750. // Output:        None
  751.  
  752. void CoolBit_Set::value_error () const {
  753.   //RAISE (Error, SYM(CoolBit_Set), SYM(Invalid_Cpos),
  754.   printf ("CoolBit_Set::value(): Invalid current position.\n");
  755.   abort ();
  756. }
  757.  
  758.  
  759. // bracket_error -- Raise exception for CoolBit_Set::operator[]() method
  760. // Input:           None
  761. // Output:          None
  762.  
  763. void CoolBit_Set::bracket_error (int n) const {
  764.   //RAISE (Error, SYM(CoolBit_Set), SYM(Out_Of_Range),
  765.   printf ("CoolBit_Set::operator[](): Bit number %d out of range.\n", n);
  766.   abort ();
  767. }
  768.  
  769.  
  770. // find_error -- Raise exception for CoolBit_Set::find() method
  771. // Input:        None
  772. // Output:       None
  773.  
  774. void CoolBit_Set::find_error (int n) const {
  775.   //RAISE (Error, SYM(CoolBit_Set), SYM(Out_Of_Range),
  776.   printf ("CoolBit_Set::find(): Bit number %d out of range.\n", n);
  777.   abort ();
  778. }
  779.  
  780.  
  781. // put_error -- Raise exception for CoolBit_Set::put() method
  782. // Input:       Start, end bit positions
  783. // Output:      None
  784.  
  785. void CoolBit_Set::put_error (int start, int end) const {
  786.   //RAISE (Error, SYM(CoolBit_Set), SYM(Invalid_Start_End),
  787.   printf ("CoolBit_Set::put(): Start bit %d greater than end bit %d.\n",
  788.       start, end);
  789.   abort ();
  790. }
  791.  
  792.  
  793. // remove_error -- Raise exception for CoolBit_Set::remove() method
  794. // Input:          None
  795. // Output:         None
  796.  
  797. void CoolBit_Set::remove_error () const {
  798.   //RAISE (Error, SYM(CoolBit_Set), SYM(Invalid_Cpos),
  799.   printf ("CoolBit_Set::remove(): Invalid current position.\n");
  800.   abort ();
  801. }
  802.  
  803.  
  804. // rem_start_end_error -- Raise exception for CoolBit_Set::remove(int,int) method
  805. // Input:                 Start, end bit positions
  806. // Output:                None
  807.  
  808. void CoolBit_Set::rem_start_end_error (int start, int end) const {
  809.   //RAISE (Error, SYM(CoolBit_Set), SYM(Invalid_Start_End),
  810.   printf ("CoolBit_Set::remove(): Start bit %d greater than end bit %d.\n",
  811.       start, end);
  812.   abort ();
  813. }
  814.  
  815.  
  816. // void set_growth_ratio (float) -- Set the growth percentage for the Vector
  817. //                                  object.
  818. // Input:                           Float ratio, type
  819. // Output:                          None
  820.  
  821. void CoolBit_Set::set_growth_ratio (float ratio) {
  822. #if ERROR_CHECKING
  823.   if (ratio <= 0.0) {                // If non-positive growth
  824.     //RAISE (Error, SYM(CoolBit_Set), SYM(Negative_Ratio),
  825.     printf ("CoolBit_Set::set_growth_ratio(): Negative growth ratio %f.\n",
  826.         ratio);
  827.     abort ();
  828.   }
  829. #endif
  830.   this->growth_ratio = ratio;            // Adjust ration
  831. }
  832.  
  833.  
  834. // void set_alloc_size (int) -- Set the default allocation size growth rate.
  835. // Input:                       Growth size in number of elements, type
  836. // Output:                      None
  837.  
  838. void CoolBit_Set::set_alloc_size (int n) {
  839. #if ERROR_CHECKING
  840.   if (n < 0) {                    // If index out of range
  841.     //RAISE (Error, SYM(CoolBit_Set), SYM(Negative_Size),
  842.     printf ("CoolBit_Set::set_alloc_size(): Negative growth size %d.\n", n);
  843.     abort ();
  844.   }
  845. #endif
  846.   this->alloc_size_s = n;            // Set growth size
  847. }
  848.